home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Technotools
/
Technotools (Chestnut CD-ROM)(1993).ISO
/
lang_c
/
cug191
/
sound.txt
< prev
next >
Wrap
Text File
|
1986-05-25
|
53KB
|
1,783 lines
S O U N D E F F E C T S
C Function Library
Version 1.0b
Copyright (C) 1986 by Paul Canniff
All Rights Reserved.
Paul Canniff
P.O. Box 1056
Marlton NJ 08053
CompuServe ID 73047,3715
Updated 05 Mar 86
C O N T E N T S
Introduction ....................... 1
Installation for Aztec C ........... 2
Installation for Ecosoft C ......... 3
Installation for Lattice C ......... 4
Installation for other compilers ... 5
Using The Library .................. 6
Making Music (using PLAY) .......... 8
Making Noise (using SOUND) ......... 10
Function Summary List .............. 11
Individual Function Descriptions ... 12
Technical Information .............. 18
What To Do When It Doesn't Work .... 23
Change Log .......................... 24
Introduction
This library facilitates the use of sound and music on the IBM-PC
family and compatibles. It has been tested with the Lattice
compiler version 2.15 and the Manx Aztec compiler version 3.20.
Other compilers (or versions of these compilers) should work just
fine, provided you can rewrite or modify the assembly-language
portions. I will be glad to help get the library working with
other compilers.
The main functions in the library are play(), sound(), and
sounds(). Play() accepts a form of musical notation, while
sounds() and sounds() accept specific frequencies and durations
for greater flexibility (at the expense of more work for the
programmer). These functions are discussed in more detail in the
sections "Making Music" and "Making Noise". Calls to sound() and
play() can be freely intermixed in either foreground or
background, providing a flexible high-level interface to the
speaker.
All of these sound-making routines can run in foreground or
background. Foreground means that the sound is generated in much
the same way that most other PC output is generated; the
application requests that it be done, the driver does it, and
then it returns to the application. This is straightforward and
clean.
Background is the fancy way. The music or the sound effects are
requested by the application, which can then continue to run
while the driver controls the speaker. This allows you to play
some music while your program performs some operations, which
might be better than just flashing WAIT at the user.
In addition, the library includes a number of low-level routines
that access the speaker directly.
1
Sound Effects General Installation
The following general installation procedure applies to all
supported compilers.
(1) First, set up your "work area", whether it be a subdirectory
on a hard disk, or a floppy disk. If you have room on a
current work disk, or in your usual C subdirectory, you may
want to use them. Wherever you decide upon, this disk or
diectory will be referred to as your "work area".
(2) Copy all .C and .H files from the distribution disk to your
work area.
(3) There are also some assembly-langauge source files which you
will need, called DELAY and SOUNDINT. There are versions of
these files on the disk for each supported compiler. Copy
the proper files to your work area, changing the extension
to .ASM in the process.
AZTEC: *.ASZ -> *.ASM
LATTICE: *.ASL -> *.ASM
ECOSOFT: *.ASE -> *.ASM
(*) Keep the original distribution disk in a safe place; all
further actions discussed should be done on your work area,
not the distribution disk.
(2) Edit the file SOUND.H and make sure that the only compiler
flag set is the one for your compiler. That flag should be
set to 1, all others to 0.
(3) Compile the C files. They include the following H files,
which should be included with your compiler:
Lattice, Ecosoft: STDIO.H, DOS.H
Aztec: STDIO.H, MODEL.H
(4) Assemble the .ASM files using the assembler provided with
your compiler, the Miscrosoft Macro Assembler, or
equivalent. The following "macro" headers are included by
the assembly files:
Lattice: DOS.MAC
(all others) -none-
(5) The file SOUNDTST is not a part of the Sound Effects
library, but is furnished as an example of an application
calling the sound functions. To test the library, link
SOUNDTST to all the sound functions, and any necessary
modules. The following modules are required:
Lattice: C.OBJ, LC.LIB
Ecosoft: ??
Aztec: C.LIB
2
Sound Effects Installation - Manx / Aztec
Manx Aztec C Version 3.20 Installation
Note: Older Manx compilers (such as version 1.06) should require
no change to the following procedure.
Before starting, set up your "work area", whether it be a
subdirectory on a hard disk, or a floppy disk. Then ...
(1) Copy the .C and .H files to your work diskette or hard disk
subdirectory. Copy all .ASL files to .ASM files on your
work area. Keep the original distribution disk in a safe
place; all further actions discussed should be done on your
work area, not the distribution disk.
(2) Edit the file SOUND.H and make sure that the only compiler
flag set to 1 is C_AZTEC.
(3) Compile the C files. They include the following H files,
which should be included with your compiler:
STDIO.H MODEL.H
(4) Assemble the .ASM files using the Manx Aztec Assembler,
Miscrosoft Macro Assembler or equivalent.
(5) Link the file SOUNDTEST.OBJ to the rest of .OBJ's produced
by the above commands, and to the C library (C.LIB).
(6) If you hear music, you have correctly installed your sound
routines. You may use LIB or PLIB86 to form them into a
library if you want. Note that you will have to repeat the
installation procedure for every memory model you use. Oh,
yes, you can delete the SOUNDTST files when you are done,
though the source gives a good example of the correct way to
access the library.
Aztec Notes
(1) Sound_done() must also be called before exiting an overlay,
if the overlay contains the Sound Effects code and data. If
both code and data of the Sound Effects functions reside in
the root, this is not necessary.
3
Sound Effects Installation - Ecosoft
Ecosoft C Version 3.02 Installation
Before starting, set up your "work area", whether it be a
subdirectory on a hard disk, or a floppy disk. Then ...
(1) Copy the .C and .H files to your work diskette or hard disk
subdirectory. Copy all .ASE files to .ASM files on your
work area. Keep the original distribution disk in a safe
place; all further actions discussed should be done on your
work area, not the distribution disk.
(2) Edit the file SOUND.H and make sure that the only compiler
flag set to 1 is C_ECOSOFT.
(3) Compile the C files. They include the following H files,
which should be included with your Lattice Compiler:
STDIO.H DOS.H
(4) Assemble the .ASM files using the Microsoft Macro Assembler
or equivalent. The file PRO.H must be present. This file
is included in the Ecosoft C package and allows the assembly
modules to know the memory model in use.
(5) Link the file SOUNDTEST.OBJ to the rest of .OBJ's produced
by the above commands, and to the Ecosoft C library
(ECOC.LIB).
(6) If you hear music, you have correctly installed your sound
routines. You may use LIB or PLIB86 to form them into a
library if you want. Note that you will have to repeat the
installation procedure for every memory model you use. Oh,
yes, you can delete the SOUNDTST files when you are done,
though the source gives a good example of the correct way to
access the library.
Ecosoft Notes
(1) The file SOUNDP.H is provided to define the Sound Effects
callable functions, using the prototype form. If you are
using prototyping, this file should be included in any
source module that calls the Sound Effects library.
4
Sound Effects Installation - Lattice
Lattice C Version 2.14 or 2.15 Installation
Note: The new Lattice compilers (version 3.xx) should require no
change to the following procedure.
Before starting, set up your "work area", whether it be a
subdirectory on a hard disk, or a floppy disk. Then ...
(1) Copy the .C and .H files to your work diskette or hard disk
subdirectory. Copy all .ASL files to .ASM files on your
work area. Keep the original distribution disk in a safe
place; all further actions discussed should be done on your
work area, not the distribution disk.
(2) Edit the file SOUND.H and make sure that the only compiler
flag set to 1 is C_LATTICE.
(3) Compile the C files. They include the following H files,
which should be included with your Lattice Compiler:
STDIO.H DOS.H
(4) Assemble the .ASM files using the Microsoft Macro Assembler
or equivalent. The file DOS.MAC must be present. This file
is included in the Lattice C package and allows the assembly
modules to know the memory model in use.
(5) Link the file SOUNDTEST.OBJ to the rest of .OBJ's produced
by the above commands, and to the Lattice C library
(LC.LIB).
(6) If you hear music, you have correctly installed your sound
routines. You may use LIB or PLIB86 to form them into a
library if you want. Note that you will have to repeat the
installation procedure for every memory model you use. Oh,
yes, you can delete the SOUNDTST files when you are done,
though the source gives a good example of the correct way to
access the library.
Lattice Notes
(1) When compiling the Sound Effects functions, be usure to use
the correct compiler flags and DOS.MAC file, so that the
Sound Effects functions are using the same memory model as
your application. You may want to compile four versions of
the Sound Effects functions, one for each memory model.
(2) Be sure to compile Sound Effects functions using the "-v"
compiler flag to disable stack checking. This is compatible
with the Lattice library. Not disabling stack checking
could result in detection of a bogus "stack overflow" during
the timer interrupt handler's execution. This will
terminate the application.
5
Sound Effects Installation - Others
Non-Supported Compilers
To use the Sound Effects library with a compiler other than
Lattice or Aztec, you will have to be familiar with your
compiler in order to customize the few assembler routines. The
following questions should be answered first. The answers for
the supported compilers are given for reference.
Lattice Manx Yours?
------- ---- ------
o Does your compiler append or prepend
an underscore to the name of each
function? N Y
o Where does the compiler put parameters? Stack Stack
o Where does your compiler place its
return values for int? AX AX
For long int? AX,BX DX,AX
o Does your compiler use near calls, far
calls, or allows both? Both Both
o What provision does your library make inp() inport()
for access to the I/O ports? outp() outport()
6
Sound Effects General Information
Using The Library
Using the Sound Effects library is similar to using the standard
library's I/O functions. There is an "open", some operations,
the a "close". In the case, the opening function is called
sound_init() and the closing function is sound_done(). One point
that cannot be stressed overmuch is the importance of calling
sound_done() before exiting the program. Any application which
uses the sound library should call sound_done() at all possible
exit points.
Note the following things about sound_done():
(1) It never hurts to call it. Sound_done() knows if
sound_init() has been called, and acts accordingly.
(2) When called it will kill any music still playing.
The opposite number of sound_done() is sound_init(), who should
(of course) be called first, before any other sound functions.
It is possible to get away without calling sound_init(), if you
want to play in mode 1. But it really is much neater to call it
anyway.
What is mode 1? Glad you asked. In the play() function, there
is a MODE sub-command which has to do with how notes are played.
But outside of that little corner, when we say "mode" we are
talking about then WHEN and HOW of the sound output.
You got a taste of the meaning of modes in the discussion of
Background and Foreground in the introduction. Real-time
programmers, forget your usual understanding of these terms. In
terms of this library music playing in Foreground plays when you
tell it to, and your application can do nothing else until the
music is finished. Music in Background is just "set up" by your
command to play, and actually plays while your application runs.
So, it is "background music" for the application, hence the
terminology.
Note that the terms music and sound are used rather
interchangeably. Music using normal notes is most easily
generated by the play() function, while sound() gives a more
flexible interface if you are into strange frequencies. Both
functions can operate in Foreground and Background.
7
Sound Effects General Information
There are actually five modes in which the sound routines can
run. See the "Technical Information" section for a more complete
description of the timing techniques. The default mode is 1.
Mode When Timing Method
---- ---------- -------------------------
1 Foreground Delay Loop
2 Foreground Standard Clock Interrupt
3 Foreground Enhanced Clock Interrupt (*)
4 Background Standard Clock Interrupt
5 Background Enhanced Clock Interrupt (*)
The mode number shown above is the value you should give to the
first parameter to sound_init(). The second parameter is sued as
a true/false flag, and tells sound_init() whether to install a
break handler. The break handler acts as a safety feature; it
makes sure that sound_done() is called before the application is
terminated by the user typing Control-C or Control-Break.
If you provide your own break handler, you will want to disable
the built-in handler. Just make sure that you included that
handler in the list of possible exits, so that it calls
sound_done() before terminating the application.
If you don't have a break handler built in to the application,
let sound_init() put one in for you.
OK, now you know that your application should look something
like this:
main()
{
sound_init(m,1);
.
.
.
sound_done();
}
That's pretty boring. You can spice it up after reading the
sections "Making Music" and "Making Noise". One more useful
function before you go ... quiet(). If you set up a long piece
of background music, and for some reason have to kill it early
(but not get ready to exit), call quiet(). It has no effect in
Foreground modes.
----------
(*) The enhanced modes currently produce the same
results as the standard modes. In a future
version these modes will provide better time
resolution. See "Tech Tips" for details.
8
Sound Effects Making Music
Making Music
(Using Play)
The play function translates a musical score into sounds. The
score is written using a special notation described below. This
notation allows the use of 8 octaves of 12 notes each, with
various tempos, etc. The format of pla() is:
void play(m)
char *m;
Commands are a single letter followed immediately by one or more
arguments, if necessary. Spaces, commas, and semicolons may
appear between commands for clarity, but are ignored by play().
A to G: These are the notes A through G, in the current octave.
A note may be followed by up to three modifiers, in
this order only:
Sharp/Flat indication: # or + is sharp;
- is flat.
Note length: number from 1 to 64 (see L)
Dots: Up to 10 dots. A dotted note plays for 3/2
of it's normal time. Two dots = 9/4, three
dots = 27/8, etc.
Examples (assuming the current note length is 4):
C+ C sharp 1/4 note
C+8 C sharp 1/8 note
B-. C sharp 1/4 note dotted = 3/8 note
A2. A 1/2 note dotted = 3/4 note
Ln Sets the current note length. Note length is 1/n, so a
parameter of 4 will set subsequent note to 1/4 notes.
Individual notes may override the current length with
an explicit length (see above examples). The range is
1 to 64.
Note length combines with tempo to determine the
duration of the note. Length is measured as a fraction
of a whole note, while tempo is in quarter-notes per
second. For example, with a tempo of 32 and a note
length of 2, a note will last for 1/16 of a second.
9
Sound Effects Making Music
Mx Sets the mode of the music. There are three modes:
x=N (NORMAL): notes are played for 7/8 of the note
time, with the remaining 1/8 being a rest.
x=S (STACCATO): notes are played for 3/4 of the note
time, with the remaining 1/4 being a rest.
x=L (LEGATO): notes are played for the full note
time, with no rest.
The modes Foreground and Background have nothing to do
with these modes !
Nn Plays note n (range 0..84), where 0 means silence. If
the argument is missing or out of range, no note is
played. Cannot be dotted or given explicit length.
On Sets octave to n (range 0..7). If argument is out of
range, current octave remains unchanged.
P[n][.] Pause or rest; see the rules for note length (n) and
dotting for the regular notes A-G above. If the
argument is missing or invalid, no pause takes place.
R Resets to default values. Resets the following:
Octave = 4
Length = 1
Mode = Normal
Tempo = 120
Tn Tempo, which may range from 32 to 255, controls the
number of quarter-notes per second. The default is
120.
< Moves down one octave. If already at octave 0, stays
there.
> Moves up one octave. If already at octave 7, stays
there.
10
Sound Effects Making Noise
Making Noise
(Using Sound and Sounds)
The function sound() and sounds() allow the program to produce
sounds other than those on the normal musical scale. The penalty
for this flexibility is that more work is usually required to
specify the frequency and duration of each sound, especially when
forming complex noises.
To produce a single sound, call sound(). Simple, eh? Just
provide the frequency as (Hz * 100), and the duration in
milliseconds. To produce a series of sounds, you can set up an
array of structures of the type sound_element and pass it to
sounds(), along with a count of the number of elements. Each
element takes up six bytes; four bytes for the frequency (long
int) and two for the duration (unsigned).
11
Sound Effects Function Descriptions
Summary Function List
These functions are described in detail later, but here is a
comprehensive list of the functions in the library, with the file
location and a short description of each one.
High-Level
sound_init SOUNDCTL Call to set mode, etc.
sound_done SOUNDCTL Call before exit.
sound_mode SOUNDCTL Returns current mode.
sound SOUND Make a noise.
sounds SOUND Make several noises.
play PLAY Make pleasant noises using easy notation.
quiet SOUNDOUT Kill playing background music.
sound_bchk SOUNDOUT Check status of sound buffer.
Low-Level
spkr_on SPKRCTL Speaker on (continuous noise)
spkr_off SPKRCTL Speaker off (blissful quiet)
spkr_freq SPKRCTL Sets the frequency of the noise
spkr_cntr SPKRCTL Sets frequency also (see func description)
Internal --- DO NOT USE
sound_out SOUNDOUT Interrupt-driven output routine
snd_irh SOUNDINT Assembly interface for sound_out
snd_brk SOUNDINT Built-in break handler
snd_giv SOUNDINT Utility - get interrupt vector
snd_siv SOUNDINT Utility - set interrupt vector
delay DELAY Internal delay loop used in mode 1
12
Sound Effects Function Descriptions
SOUND_INIT and SOUND_DONE
Purpose:
Set up and tear down the interrupt vectors needed to provide
sound.
Summary:
int sound_init(mode,install_bh)
int mode, install_bh;
int sound_done();
Parameters:
Mode: Must be in the range 1..5; sets the mode for
subsequent calls to sound() and play().
Values are:
1 Foreground w/ Delay Loop
2 Foreground w/ Standard Clock Interrupt
3 Foreground w/ Enhanced Clock Interrupt
4 Background w/ Standard Clock Interrupt
5 Background w/ Enhanced Clock Interrupt
Install_bh: If this is 0, no break-handler will be
installed. Otherwise, a break handler will
be installed. See Technical Information for
a complete description of the break handler.
Returns:
Zero indicates success. Sound_init will return -1 if an
invalid mode is passed.
Notes:
Sound_init() may be called more than once without harmful
effects. When called, any music currently playing will be
killed. You can use calls to sound_init() to change modes
during the application.
Sound_done() shust off background music and the speaker, and
cleans up any interrupt vectors which may have been changed
by sound_init(). This lets the application safely exit.
13
Sound Effects Function Descriptions
SOUND_MODE
Purpose:
Returns the current sound mode. See sound_init() for the
possible values.
Summary:
int sound_mode()
Parameters:
None
Returns:
Returns current mode, range 1-5. See sound_init()
description for complete list of modes.
14
Sound Effects Function Descriptions
SOUND & SOUNDS
Purpose:
Produce a sound or sounds for a certain time.
Summary:
void sound(freq,dur)
long freq;
unsigned dur;
void sounds(n,sa)
int n;
struct sound_desc *sa;
Parameters:
freq: Frequency in MHz * 10. Ex: 400MHz passed as 40000L.
The allowable range is ???. A frequency of 0 is
treated as "silence". A sound with a duration of 0
is ignored.
dur: Duration of sound in milliseconds.
n: Number of sounds passed. Numbers less than zero are
treated as zero.
sa: Array of sound descriptions, each containing a
frequency and a duration, as per the freq and dur
parameters passed to sound.
Returns:
0 if all parameters all OK
-1 if error in parameters (out of range).
Error Handling:
Checks parameter range only.
Notes:
These functions are effected by the mode currently set by
the most recent call to sound_init. They may be used for
either foreground or background operation.
15
Sound Effects Function Descriptions
PLAY
Purpose:
Play a series of musical notes using an easy notation.
Summary:
void play(music)
char *music;
Parameters:
The music parameter is a string which can contain many
complex operations, all of which are described in the
section "Making Music".
Returns:
Nothing.
Error Handling:
Any problems encountered in the music string are handled as
described in the section "Making Music."
Notes:
The play function introduces an amount of overhead in terms
of code size, as it must parse the string. A program which
is memory-critical should use sounds(); of course the
programmer must then perform the task of converting each
note into one or more sounds.
See "Making Music" for details on play()'s operation.
16
Sound Effects Function Descriptions
DIRECT SPEAKER CONTROL FUNCTIONS
Purpose:
Direct control of speaker port.
Summary:
void spkr_on()
void spkr_off()
void spkr_freq(f)
long f;
void spkr_cntr(c)
unsigned c;
Parameters:
The parameter to spkr_freq is the frequency in MHz to set
the speaker to. The parameter to spkr_cntr is the actual
counter value to be passed to the 8253 timer chip. Note
that the only functions to actually turn the speaker on or
off are spkr_on and spkr_off; setting the frequency does
not imply activating or deactivating the speaker.
Returns:
Nothing.
Error Handling:
None.
Notes:
Unlike sound(), sounds(), and play(), which can be freely
intermixed, use of these low-level functions while in
background mode can disrupt the background music. While
this is far from fatal, is can produce unpleasant noises.
Call quiet() before using these functions.
17
Sound Effects Function Descriptions
BACKGROUND-BUFFER FUNCTIONS
Purpose:
Control music playing in background.
Summary:
void quiet()
void sound_bchk(used,avail)
int *used, *avail;
Parameters:
quite: none.
sound_buffchk(): used to return values (see below).
Returns:
quiet() has no return value.
buffchk() returns the number of sound elements in the buffer
and the number of free elements, via the parameters "used"
and "avail" respectively.
Error Handling:
None.
Notes:
A call to quiet will kill any background music, flush the
buffer, and shut off the speaker.
18
Sound Effects Technical Information
=======================
TECHNICAL INFORMATION
=======================
I have tried to be clear and precise in these technical notes.
Should you find any errors in code or documentation, or have
suggestions for improvement, I would appreciate your feedback.
These paragraphs are not for the faint of heart. For more
details, I suggest some of Peter Norton's excellent PC books,
and the ever-cryptic but fact-filled IBM Technical Reference.
Here is a brief summary of this section:
Timing Sound Duration (MODES)
Delay Loop - How, Pro & Con
Timer Interrupt - How, Pro & Con
Enhanced Interrupt - How, Pro & Con
Sound Generation Mechanics
Speaker Logic
Setting The Frequency
The Background Buffer
The Break Handler
The Interrupt Handler
=========================
TIMING THE SOUND DURATION
=========================
There are five modes in which the sound routines can run. They
define WHEN the music plays, and how the proper DURATION is
determined. The FREQUENCY of the sounds is always determined and
produced by the same method regardless of mode, and is described
a few paragraphs below.
Mode When Timing
---- ---- ------
1 Foreground Delay Loop
2 Foreground Standard Clock Interrupt
3 Foreground Enhanced Clock Interrupt
4 Background Standard Clock Interrupt
5 Background Enhanced Clock Interrupt
The default mode is mode 1. It poses the fewest problems, but
has some limitations. The timing is achieved using a delay loop,
which is simply a small piece of code with a known execution
time. By looping through this piece of code you can approximate
the duration of the sounds fairly well.
19
Sound Effects Technical Information
Unfortunately, the delay loop method has problems. It is very
dependent on the hardware, for one thing. A processor running
at 8MHz will execute the code in close to half the time of a
standard PC running at 4.77MHz, so the sounds will be shorter.
Also, the timing becomes dependent on processor type. The normal
PC has an 8088; on an AT&T 6300 (8086) or on a PC-AT (80286),
there will be a noticeable timing difference due to the varying
bus widths and execution speeds, even if the base processor clock
speed was the same. And as the coup-de-grace, this method will
be thrown off by the occurance of interrupts. An interrupt will
cause other code to be executed which will extend the execution
time of the loop.
Fortunately there is a better timing method available. There is
an on-board main system clock chip which provides a pulse with a
frequency of about 1.19MHz. This is stepped down to a more
reasonable rate by the 8253 counter chip. The most familiar use
of this is to provide the system tick, which occurs 18.2 time a
second and generates the hardware clock interrupt (IRQ0, INT 8).
This is generally independent of the clock speed of the
processor, and so is a good timing source across the extended PC
family.
We can use this system tick to time the sounds. Both foreground
and background methods can do this; the foreground modes will
merely wait around until the sound is over. Therefore the
following discussions of the use of the system tick interrupt
apply to both foreground and background.
The standard interrupt modes (2 and 4) tie into the software
interrupt vector 0x1C. This is the "user timer interrupt"
vector, and is provided by the BIOS as a nice way to tie software
into the timer. The BIOS interrupt handler retains all
responsibility for handling the messy tasks of sending end-of-
interrupt to the interrupt controller chip, incrementing the
time-of-day clock tick, etc. This is a clean way to use the
system tick to time events.
Possible Problems
There are only two possible problems (that I can see) to using
the system tick. One is that some memory-resident software
packages are very possessive about interrupts. That is why so
many of them are incompatible with each other. In theory, any
number of drivers could share the user system tick by chaining
themselves together, but they often don't. This software does,
so it will work with well-behaved utilities.
The other problem mainly involves background mode. If the user
aborts the program by using control Ctrl-Break, interrupt vectors
will not be restored, and eventually the system will crash and
need rebooting. This can be prevented by using the provided
break handler (see SOUND_INIT) or by calling sound_done() if your
application already provides its own break handler.
20
Sound Effects Technical Information
Enhanced Modes
The enhanced interrupt modes (3 and 5) are not yet fully
implemented, and are presently the same as modes 2 and 4
respectively. In a future release, they will follow the example
of BASIC and change the system tick generation to provide better
resolution. This tick is sped up by a factor of 4. The sound
system must intercept this tick at the INT 8 level, and provide
the tick to the BIOS only every fourth time, to keep the system
time-of-day clock from speeding ahead. The advantage is better
time resolution.
The disadvantages to the enhanced modes include all of the ones
given for the standard clock modes, plus the code has to dig even
deeper into territory where applications programs are not
encouraged to venture. Still, taking proper care to restore
vectors upon exit, this should be clean enough for everyday use.
There is a question as to the value of the more precise timing of
the sounds, which may not be of great importance anyway.
==========================
SOUND GENERATION MECHANICS
==========================
Speaker Logic
The sounds are produced using the speaker attached to the IBM
motherboard. The speaker is pulsed to provide sound of the
desired frequency. The pulsing action is provided courtesy of
the main system clock, stepped down through the 8253
programmable counter. There is also an on/off switch provided by
a bit in the PPI chip. The speaker control circuitry is
logically (not electrically) diagrammed as:
+-------+ +--------+
| 8284A |--->| 8253-5 |----+
+-------+ +--------+ | ____ /|
+--> ) \ / |
|AND >---------->[ |
+--> )___/ \ |
+-----+ | \|
| PPI |----------+
+-----+ Speaker
The PPI switch is accessed as bits 0 and 1 at I/O address 0x61.
When the bits are set the speaker switch is on, when cleared the
speaker switch is off. See the spkr_on() and spkr_off()
functions to see how to do this from C. Note that the value of
the PPI is first read, the required bits changed, and then
written out. This is necessary because the PPI has many other
uses for the rest of the bits.
21
Sound Effects Technical Information
Setting Frequency using the 8253
The system clock oscillates at about 1.19MHz. The 8253
programmable counter steps down this frequency by sending a pulse
for every so many input pulses. The well-known system tick of
18.2 ticks per second is obtained using this chip and a divisor
of 0xFFFF. The chip has two counters; while one output connects
to the system clock interrupt, the other ties to the speaker.
So, by changing the divisor in the counter, we can change the
frequency of the pulses sent to the speaker and hence the
frequency of the sound it produces.
For more details on the use of the 8253 programmable counter,
consult the Intel part spec.
=====================
THE BACKGROUND BUFFER
=====================
Sounds to be played in modes 2 through 5 are placed in a buffer
and played under interrupt control. Since this buffer is of
finite size, it is possible to overflow. Overflowing sounds will
be discarded.
Each entry takes up four (4) bytes, and the number of entries in
the buffer is fixed when you build the library. The compiled
files on the disk have a default buffer size of 64 entries. You
can change this by changing the value of the constant
SND_BUFFSIZE in SOUND.H and recompiling the system.
Each note sent to play() will usually generate two entries, one
for the note and one for the inter-note pause. Using sound() and
sounds() will generate exactly one entry per sound element.
The sound buffer is circular, so that as entries are output to
the speaker, more can be added. Check the status of the buffer
using the function sound_bchk(), which will get you both the
number of entries used and the number of entries free.
===================
THE BREAK HANDLER
===================
The built-in break handler has a simplistic view of life. It
accepts control, calls sound_done() to clean up, then passes
control to the break handler that precedes it. This means that
the usual net result is an exit to DOS, but safely. Feel free to
use the given function as a template, but keep the original
around in case you accidentally muck it up a bit.
22
Sound Effects Technical Information
=======================
THE INTERRUPT HANDLER
=======================
This refers to the timer interrupt handler, a very simple
routine. Its job is to save the registers, load the segment
registers that C functions expect, call sound_out() to do all the
work, and restore all the registers. It then calls the routine
which was previously the interrupt handler. This is a nice
courteous thing to do, as it allows sharing of this valuable
resource, the system tick.
23
Sound Effects Technical Information
WHEN THINGS GO WRONG
First of all, please feel free to ask me (the author) questions.
I cannot accept phone questions at this time, mainly because I am
not near any particular phone during the day. You can reach me
by mail or by CompuServe EASYMAIL (73047,3715). But first, see
if the following list has your problem on it.
"I cannot read the distribution disk."
The distribution disk is provided in IBM double-sided 9-
sector format. You will not be able to read it with single-
sided drives or with a DOS version before 2.0.
If you can read such disks normally, there is a chance that
the diskette has been damaged in transit. Please return the
diskette and you will get another copy, no charge.
"The files will not compile on my system."
If you are using a non-supported compiler, all I can do is
refer you to the section on Setting Up for Other Compilers".
If you do get everything working, even if just on a
different version of Lattice or Manx/Aztec, I would
appreciate if you let me know. I will do everything I can
to help you get it compiled and running, but without a copy
of the compiler (DO NOT SEND ME COPYRIGHTED SOFTWARE) I
cannot promise much.
Be sure you have the file SOUND.H where your compiler can
find it. Also be sure that you have enough room on your
diskettes for the compiler's output.
"My system locks up when I run a program using sound."
First, if you have any memory-resident utilities, let's get
rid of them for the moment. De-install them, even remove
them from your AUTOEXEC.BAT file, then reboot the system.
Try the program again. If it still crashes ...
Make sure you are calling quiet() before the program exits.
24
Sound Effects Technical Information
==========
CHANGE LOG
==========
Version 1.0b (OPEN)
Added new file SOUNDP.H containing prototypes for all
user-callable functions, for compilers which support
prototyping.
Added support for Ecosoft Eco-C88 compiler.
Compressed definition of Install in SOUNDCTL, by combining
all definitions using typedef's and #defines to allow for
compiler and library differences.
Version 1.0a (2/20/85)
Delay now written in assembler.
Corrected error in play(), which would not play dotted
notes if a length was also specified.
Corrected error in SOUND.H's definition of MS2TICKS, which
was miscalculated and rounding badly.
25